﻿#-------------------------------------------------------------------------------
# Name:        mapworker
# Purpose:     loading matrix of allowed positions to build and "waypoints" for
#              monsters, and many other things. Requires pygame.
#
# Author:      Lorien
#
# Created:     11.08.2011
# Copyright:   (c) ASM-team 2011
# Licence:     Private
#-------------------------------------------------------------------------------
#!/usr/bin/env python

import queue
import os

import pygame


class MapWorker:
    """
    Handling all map loading routing
    """

    def __init__(self, filename):
        self.spawn_points = []
        ##self.spawn_times = []
        self.aim_points = []
        self.map_name = ""
        self.map_bmp = ""
        self.map_matrix = 0
        self.map_objects = 0

        with open(filename) as map_file:
            self.dirname = os.path.dirname(filename)
            self.map_name = map_file.readline().strip()
            self.map_bmp = map_file.readline().strip()
            self.background = map_file.readline().strip()
            self.start_money = int(map_file.readline().strip())
            self.map_size = tuple(map(int, map_file.readline().strip().split()))
            # spawns {time: (count, type)}
            self.spawns = dict()
            tmp = map_file.readline().strip().split()  # [10:50:1, 20:50:1, 30:50:2]
            for item in tmp:
                elem = item.split(':')                 # [10:50:1]
                self.spawns[int(elem[0])] = tuple(map(int, elem[1:]))   # spawns[10] = (50, 1)
                ##self.spawn_times = map_file.readline().strip().split()
        self.load(self.map_bmp)

    def load(self, filename):
        """
        maploader.MapLoader.load (filename): return 2darray
        Returns 2d array formed from bmpfile.
        """
        surface = pygame.image.load(os.path.join(self.dirname, filename))
        width = surface.get_width()
        height = surface.get_height()
        self.width = width
        self.height = height

        #Getting pixels
        pixels = pygame.PixelArray(surface)

        #Creating width*height array: [0..width-1][0..height-1]
        self.map_matrix = [[-2] * height for x in range(width)]
        self.map_objects = [[False] * height for x in range(width)]

        walkcount = 0
        #Lets fill the array!
        for x in range(width):
            for y in range(height):
                color = pixels[x][y]
                colorPix = surface.unmap_rgb(pixels[x][y])
                if color == surface.map_rgb((0, 255, 0)):  # Can build
                    self.map_matrix[x][y] = - 1
                elif colorPix.g == 0 and colorPix.r == 255:  # Can walk
                    self.map_matrix[x][y] = 1
                    walkcount += 1
                elif colorPix.g == 127 and colorPix.r == 255:  # Respawn
                    self.map_matrix[x][y] = 0
                    self.spawn_points.append((x, y))
                elif colorPix.g == 128 and colorPix.r == 255:  # Aim
                    self.map_matrix[x][y] = 2
                    self.aim_points.append((x, y))

        # Build the fucking waypoints
        max = walkcount + 2

        q = queue.Queue()
        for point in self.aim_points:
            color = surface.unmap_rgb(pixels[point[0]][point[1]])
            self.map_matrix[point[0]][point[1]] = max * 100 * (color.b + 1)
            q.put(point)

        while not q.empty():
            point = q.get()
            color = surface.unmap_rgb(pixels[point[0]][point[1]])
            weight = self.map_matrix[point[0]][point[1]]

            new_points = [(point[0], point[1] + 1), (point[0], point[1] - 1), (point[0] + 1, point[1]),
                          (point[0] - 1, point[1])]
            for new_point in new_points:
                if 0 <= new_point[0] < width and 0 <= new_point[1] < height:
                    newcolor = surface.unmap_rgb(pixels[new_point[0]][new_point[1]])
                    if (0 <= self.map_matrix[new_point[0]][new_point[1]] < weight - 1 and
                                newcolor.b == color.b):
                        q.put(new_point)
                        self.map_matrix[new_point[0]][new_point[1]] = weight - 1

    def canBuild(self, point:tuple, tower):
        width = tower.width
        height = tower.height
        try:
            for x in range(int(point[0]), int(point[0]) + width):
                for y in range(int(point[1]), int(point[1]) + height):
                    if self.map_matrix[x][y] != -1:  # area is not for building
                        return False
                    if self.map_objects[x][y]:  # area is already built on
                        return False
        except IndexError:  # тыкнули на границе экрана, либо на панель GUIшки
            return False
        return True

    def addToMap(self, gobject):
        #setting our placement
        for x in range(int(gobject.x), int(gobject.x) + gobject.width):
            for y in range(int(gobject.y), int(gobject.y) + gobject.height):
                self.map_objects[x][y] = gobject


if __name__ == '__main__':
    map = MapWorker("map.tdmap")
